namespace designpatternsplus.contracts
{
    #region

    using System;

    #endregion

    /// <summary>
    /// Defines the enum for display
    /// and derives categorization rules
    /// </summary>
    public sealed class ProductType
    {
        readonly ItemCategory _abbrev;

        /// <summary>
        /// Initializes a new instance of the <see cref="ProductType"/> class.
        /// </summary>
        /// <param name="abbrev">The abbrev.</param>
        public ProductType(ItemCategory abbrev)
        {
            _abbrev = abbrev;
        }

        /// <summary>
        /// Gets a value indicating whether this instance is tax except.
        /// </summary>
        /// <value>
        /// 	<c>true</c> if this instance is tax except; otherwise, <c>false</c>.
        /// </value>
        public bool IsTaxExempt
        {
            get
            {
                switch (Category)
                {
                    case ItemType.Food:
                    case ItemType.Medical:
                    case ItemType.Books:
                        return true;
                    case ItemType.Other:
                        return false;
                    default:
                        throw new ArgumentOutOfRangeException();
                }
            }
        }

        /// <summary>
        /// Gets the category.
        /// </summary>
        /// <value>The category.</value>
        public ItemType Category
        {
            get { return (ItemType) this; }
        }

        /// <summary>
        /// Gets the abbreviation.
        /// </summary>
        /// <value>The abbreviation.</value>
        public ItemCategory Name
        {
            get { return _abbrev; }
        }

        public override string ToString()
        {
            return Name.ToString();
        }

        /// <summary>
        /// Performs an implicit conversion from 
        /// <see cref="ProductType"/> 
        /// to <see cref="ItemCategory"/>.
        /// </summary>
        /// <param name="from">From.</param>
        /// <returns>The result of the conversion.</returns>
        public static explicit operator ItemType(ProductType from)
        {
            ItemType result;

            switch (from.Name)
            {
                case ItemCategory.NietzcheThusSpoke:
                    result = ItemType.Books;
                    break;
                case ItemCategory.PharmacyAhMyHeadHurts:
                    result = ItemType.Medical;
                    break;
                case ItemCategory.HersheysCandyBar:
                case ItemCategory.ChocolateInBoxPieces:
                case ItemCategory.ChocolateImportedGoodPrice:
                    result = ItemType.Food;
                    break;
                case ItemCategory.TheSmithsLouderThanBombsMusicCd:
                case ItemCategory.PerfumeLowEnd:
                case ItemCategory.PerfumeTopFrenchBrand:
                case ItemCategory.PerfumeJerseysFinest:
                case ItemCategory.PerfumeMadeInChina:
                    result = ItemType.Other;
                    break;
                default:
                    throw new ArgumentOutOfRangeException();
            }

            return result;
        }
    }
}